package event;

import java.util.ArrayList;
import java.util.List;

public class EventService {

	private static EventService singleton = null;
	private List<Subscription> subscriptions;
	private Class<?> eventClass;

	private EventService() {
		eventClass = Event.class;
		subscriptions = new ArrayList<Subscription>();
	}

	public static EventService getInstance() {
		if (singleton == null) {
			singleton = new EventService();
		}
		return singleton;
	}

	public void publish(Event event) {
		for (Subscription aSubscription : subscriptions) {
			if (aSubscription.getEventType().isAssignableFrom(event.getClass())
					&& (aSubscription.getFilter() == null || aSubscription
							.getFilter().apply(event))){
				aSubscription.getSubscriber().inform(event);
			}
		}
	}

	public void subscribe(Class<?> eventType, Filter filter,
			Subscriber subscriber) throws InvalidEventTypeException {
		if (!eventClass.isAssignableFrom(eventType))
			throw new InvalidEventTypeException(eventType
					+ " is not assignable from " + eventClass);
		Subscription subscription = new Subscription(eventType, filter,
				subscriber);
		if (!subscriptions.contains(subscription))
			subscriptions.add(subscription);
	}

	public void unsubscribe(Class<?> eventType, Filter filter,
			Subscriber subscriber) throws InvalidEventTypeException {
		if (!eventClass.isAssignableFrom(eventType))
			throw new InvalidEventTypeException(eventType
					+ " is not assignable from " + eventClass);
		subscriptions.remove(new Subscription(eventType, filter, subscriber));
	}
}
